package logic;
 
import java.nio.ByteOrder;
import java.util.Calendar;
import java.util.concurrent.TimeUnit;

import javax.swing.JTextArea;

import io.netty.handler.codec.LengthFieldBasedFrameDecoder;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;

import org.apache.log4j.Logger;

import io.netty.bootstrap.Bootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.EventLoop;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.timeout.IdleStateHandler;

public class NettyClient {
    private String host;
    private int port;
    private Channel channel;
    private Bootstrap b = null;
    
    // 日志对象
    private final static Logger logger = Logger.getLogger(NettyClient.class);
    // 配置信息
    private final ConfigInfo configInfo = ConfigInfo.getInstance();
    // 文本框对象
 	JTextArea sendArea;
 	// 连接失败
 	final String connectFail = "与服务器建立连接失败,尝试重新连接...";
 	// 连接成功
 	final String connectSuccess = "与服务器建立连接成功...";
 
    public NettyClient(String host, int port, JTextArea sendArea) {
        this.host = host;
        this.port = port;
        this.sendArea = sendArea;
        init();
    }
 
    private void init() {
        b = new Bootstrap();
        EventLoopGroup workerGroup = new NioEventLoopGroup();
        b.group(workerGroup).option(ChannelOption.SO_KEEPALIVE, true)
                .channel(NioSocketChannel.class)
                .handler(new ChannelInitializer<SocketChannel>() {
                    @Override
                    protected void initChannel(SocketChannel socketChannel) throws Exception {
                        ChannelPipeline pipeline = socketChannel.pipeline();
                        /*pipeline.addLast(new DelimiterBasedFrameDecoder(Integer.MAX_VALUE,
                                Unpooled.copiedBuffer(System.getProperty("line.separator").getBytes())));*/
                        //字符串编码解码 
                        //pipeline.addLast("decoder", new ByteArrayDecoder());
                        //pipeline.addLast("encoder", new ByteArrayEncoder());
                        
                        if (configInfo.encoderStyle == 1) {

                            logger.info("===================" + configInfo.byteOrder);
                            //pipeline.addLast(new LengthFieldBasedFrameDecoder(ByteOrder.LITTLE_ENDIAN, 0xffff, 4, 2, 0, 0, true));
                        	// 字节数组传输
	                        if (configInfo.byteOrder == 1) {
                                logger.info("。。。。。。。。。。。。。。。。" + configInfo.byteOrder);
		                        // 小端字节顺序	
	                        	pipeline.addLast(new LengthFieldBasedFrameDecoder(ByteOrder.LITTLE_ENDIAN, 0xffff, 4, 2, 0, 0, true));
	                        } else {
	                        	// 大端字节顺序
	                        	pipeline.addLast(new LengthFieldBasedFrameDecoder(ByteOrder.BIG_ENDIAN, 0xffff, 4, 2, 0, 0, true));
	                        }
                        } else {
                        	// 字符串传输
                        	pipeline.addLast("decoder", new StringDecoder());
                            pipeline.addLast("encoder", new StringEncoder()); 
                        }
                        
                        //心跳检测
                        pipeline.addLast(new IdleStateHandler(0, configInfo.heartInterval, 0, TimeUnit.SECONDS));
                        //客户端的逻辑
                        pipeline.addLast("handler", new NettyClientHandler(NettyClient.this, sendArea));
                    }
                });
        
    }
 
    public void start() {
        ChannelFuture f = b.connect(host, port);

        // 重连时更新时间戳
        Monitor.timestamp = Calendar.getInstance().getTimeInMillis();
        f.addListener(new ChannelFutureListener() {
            @Override
            public void operationComplete(ChannelFuture channelFuture) throws Exception {
                if (!channelFuture.isSuccess()) {
                	Utils.recordMsg(sendArea, connectFail);
                	logger.error(connectFail);
                	// 如果服务端没有启动,则每隔2秒向服务端发送联机请求
                    final EventLoop loop = channelFuture.channel().eventLoop();
                    // logger.info(channelFuture.channel().isActive() + ", " + channelFuture.channel().isActive());
                    loop.schedule(new Runnable() {
                        @Override
                        public void run() {
                            start();
                        }
                    }, 2L, TimeUnit.SECONDS);
                } else {
                    channel = channelFuture.channel();
                    logger.info(connectSuccess);
                    Utils.recordMsg(sendArea, connectSuccess);
                }
            }
        });
    }
 
    public Channel getChannel() {
        return channel;
    }
}